﻿using System;
using System.Text;

namespace ZProto
{
    public class BuffReader
    {
        private byte[] _buff;
        private int _index;
        public BuffReader(byte[] buff)
        {
            Reset(buff);
        }
        public void Reset(byte[] buff)
        {
            _buff = buff;
            _index = 0;
        }
        public unsafe bool _bool()
        {
            fixed (byte* ptr = _buff)
            {
                var value = *(bool*)(ptr + _index);
                _index += sizeof(bool);
                return value;
            }
        }
        public unsafe byte _byte()
        {
            return _buff[_index++];
        }
        public unsafe sbyte _sbyte()
        {
            return (sbyte)_buff[_index++];
        }
        public short _short()
        {
            return (short)_ushort();
        }
        public unsafe ushort _ushort()
        {
            fixed (byte* ptr = _buff)
            {
                var value = *(ushort*)(ptr + _index);
                _index += sizeof(ushort);
                return Utils.Endian(value);
            }
        }
        public int _int()
        {
            return (int)_uint();
        }
        public unsafe uint _uint()
        {
            fixed (byte* ptr = _buff)
            {
                var value = *(uint*)(ptr + _index);
                _index += sizeof(uint);
                return Utils.Endian(value);
            }
        }
        public long _long()
        {
            return (long)_ulong();
        }
        public unsafe ulong _ulong()
        {
            fixed (byte* ptr = _buff)
            {
                var value = *(ulong*)(ptr + _index);
                _index += sizeof(ulong);
                return Utils.Endian(value);
            }
        }
        public float _float()
        {
            return Utils.uint2float(_uint());
        }
        public double _double()
        {
            return Utils.ulong2double(_ulong());
        }
        public string _string()
        {
            var size = _ushort();
            if (size == 0)
                return string.Empty;
            var value = Encoding.UTF8.GetString(_buff, _index, size);
            _index += size;
            return value;
        }
        public T[] _array<T>(Func<T> read)
        {
            var size = _int();
            var array = new T[size];
            for (var i = 0; i < size; ++i)
            {
                array[i] = read();
            }
            return array;
        }
    }
}
